package com.ys.erp.framework.response;

import com.ys.erp.framework.annotation.ResponseResult;
import com.ys.erp.framework.config.FeignClientConfig;
import jakarta.annotation.Nonnull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Conditional;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * @author Administrator
 */
@Slf4j
@RestControllerAdvice
@Conditional(ResponseOpenHandler.class)
public class BaseResponseBodyHandler implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(MethodParameter methodParameter, @Nonnull Class<? extends HttpMessageConverter<?>> aClass) {
        // 判断是否需要处理返回数据
        return methodParameter.getContainingClass().isAnnotationPresent(ResponseResult.class)
                || methodParameter.hasMethodAnnotation(ResponseResult.class);
    }

    @Override
    public Object beforeBodyWrite(Object body, @Nonnull MethodParameter methodParameter, @Nonnull MediaType mediaType,
                                  @Nonnull Class<? extends HttpMessageConverter<?>> aClass,
                                  @Nonnull ServerHttpRequest serverHttpRequest, @Nonnull ServerHttpResponse serverHttpResponse) {
        HttpHeaders headers = serverHttpRequest.getHeaders();
        log.debug("ResponseBodyHandler beforeBodyWrite：{}", body);
        // 如果是 Feign 请求，则不进行包装
        if (headers.containsKey(FeignClientConfig.IS_FEIGN)) {
            log.debug("Feign 请求，不进行包装");
            return body;
        }
        if (body instanceof ResponseDTO) {
            log.debug("ResponseDTO 对象数据，直接返回");
            return body;
        }
        // 对于String类型返回值，直接返回，避免类型转换异常
        if (body instanceof String) {
            log.debug("String 类型数据，直接返回");
            return body;
        }
        return ResponseDTO.createBySuccess(body);
    }
}